import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

public class Elastico extends Applet implements Runnable, ActionListener, MouseListener {

	
	/*  1) problema colore elastico che va sopra la base
	 *  2) aggiustare colore pannelli
	 *  4) commenti + javadoc
	 *  
	 * */
	/**
	 * Oggetto Image per evitare lo sfarfallamento
	 */
	
	private Image offScreenImage;
	
	/**
	 * Oggetto CanvasUtente su cui disegnare
	 */
	
	private CanvasUtente tela;
	
	/**
	 * Etichetta che mostra un errore
	 */
	
	private Label errore;
	
	/**
	 * TexField per selezionare il numero di molle da aggiungere o eliminare
	 */
	
	private TextField nMolle;
	
	/**
	 * TexField per selezionare la molla da modificare
	 */
	
	private TextField molla;
	
	/**
	 * Scrollbar per scegliere il colore della pallina
	 */
	
	private Scrollbar coloreP;
	
	/**
	 * Scrollbar per scegliere il colore del punto
	 */
		
	private Scrollbar coloreB;
	
	/**
	 * Scrollbar per scegliere il diametro della pallina
	 */
	
	private Scrollbar dPalline;
	
	/**
	 * Scrollbar per scegliere il diametro del punto
	 */
	 
	private Scrollbar dBasi;
	
	/**
	 * Scrollbar per scegliere la massa
	 */
	
	private Scrollbar massa;
	
	/**
	 * Scrollbal per il coefficiente di attrito
	 */
	
	private Scrollbar attrito;
	
	/**
	 * Scrollbal per la costante elastica
	 */
	
	private Scrollbar kElastica;
	
	/**
	 * Thread dell'applet
	 */
	
	private Thread t;
	
	/**
	 * Inizializza l'applet creando la tela e i 2 pannelli
	 */
	
	public void init() {

		/* Crea un nuovo Canvas su cui disegnare, imposta la posizione, le dimensioni e il colore di sfondo */
		tela = new CanvasUtente();
		setBounds(0,0,800,600);
		setBackground(Color.WHITE);
		setLayout(new BorderLayout());
		
		/* Crea i 2 pannell1 */
		Panel p1 = new Panel();
		Panel p2 = new Panel();
		add(tela, BorderLayout.EAST);
	
		/* Imposta il colore dello sfondo */
		p1.setBackground(Color.LIGHT_GRAY);
		p2.setBackground(Color.LIGHT_GRAY);
		
		/* Aggiungi gli elementi al pannello p1 */
		p1.add(new Label(""));
		p1.add(new Label("Numero Molle"));
		nMolle = new TextField("10");
		p1.add(nMolle);

		p1.add(new Label(""));
		p1.add(new Label("Molla"));
		molla = new TextField("1");
		p1.add(molla);
		Label descr = new Label("0 per modificare tutte le molle");
		p1.add(descr);
		
		p1.add(new Label(""));
		p1.add(new Label("Colore delle Basi"));
		coloreB = new Scrollbar(Scrollbar.HORIZONTAL,Color.BLACK.getRGB()/2, 1, Color.BLACK.getRGB(), Color.WHITE.getRGB());
		p1.add(coloreB);
		
		p1.add(new Label(""));
		p1.add(new Label("Colore delle Palline"));
		coloreP = new Scrollbar(Scrollbar.HORIZONTAL,Color.RED.getRGB()/2, 1, Color.BLACK.getRGB(), Color.WHITE.getRGB());
		p1.add(coloreP);
		
		p1.add(new Label(""));
		p1.add(new Label("Dimensione delle Basi"));
		dBasi = new Scrollbar(Scrollbar.HORIZONTAL,10,1,5,50);
		p1.add(dBasi);
				
		p1.add(new Label(""));
		p1.add(new Label("Dimensione delle Palline"));
		dPalline = new Scrollbar(Scrollbar.HORIZONTAL,10,1,5,50);
		p1.add(dPalline);
		
		p1.add(new Label(""));
		p1.add(new Label("Massa delle Palline"));
		massa = new Scrollbar(Scrollbar.HORIZONTAL,10,1,1,80);
		p1.add(massa);

		p1.add(new Label(""));
		p1.add(new Label("Coeff. Attrito"));
		attrito = new Scrollbar(Scrollbar.HORIZONTAL,1,1,1,10);
		p1.add(attrito);

		p1.add(new Label(""));
		p1.add(new Label("Costante Elastica"));
		kElastica = new Scrollbar(Scrollbar.HORIZONTAL,1,1,1,20);
		p1.add(kElastica);
		errore = new Label("");
		errore.setAlignment(Label.LEFT);
		p2.add(errore);
		
		p1.setLayout(new GridLayout(28, 1 ,1 ,1));
		p2.setLayout(new GridLayout(1, 2 ,1 ,1));
		
		add(p2, BorderLayout.SOUTH);
		add(p1, BorderLayout.WEST);
		/* Listener vari */
		tela.addMouseListener(this);

		/* Gestisci gli eventi relativi alle scrollbar */
		coloreB.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setColor("b",e.getValue(),Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		coloreP.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setColor("p",e.getValue(),Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		dBasi.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setDiametro("b",e.getValue(), Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		dPalline.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setDiametro("p",e.getValue(), Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		massa.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setMassa(e.getValue(),Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		attrito.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setAttrito(e.getValue()/(double)10, Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		kElastica.addAdjustmentListener(new AdjustmentListener(){
			public void adjustmentValueChanged(AdjustmentEvent e) {
				try {
					tela.setK(e.getValue()/(double)10, Integer.parseInt(molla.getText())-1);
				}
				catch (ArrayIndexOutOfBoundsException e1) {
					errore.setText("ERRORE: La pallina selezionata non esiste");
				}
			}
		});
		
		nMolle.addActionListener(this);
		molla.addActionListener(this);
	}
	
	/**
	 * Avvia l'applet e il thread principale
	 */
	
	public void start() {
		tela.start();
		t = new Thread(this);
		t.start();
	}
	
	/**
	 * Avvia il thread eseguendo un ciclo che ogni 20 ms richiami il repaint()
	 */
	
	public void run() {
		while(true) {
			try {
				t.sleep(20);
			}
			catch( InterruptedException e) { System.out.println("Eccezzione: "+e); } 
			repaint();
		}
	}
	
	/**
	 * Aggiorna l'immagine evitando lo sfarfallio
	 */
	
	public void update(Graphics g) {
		if(offScreenImage != null) {
				// Salvo di passo in passo il foglietto aggiornando poi solo 
				// con le nuove coordinate
				Graphics offScreenGraphics = offScreenImage.getGraphics();
				/* Imposta il colore  finestra */
				offScreenGraphics.setColor(getBackground()); 
				/* Cancella la parte vecchia disegnando un rettangolo dello stesso colore della finestra */
				offScreenGraphics.fillRect(0, 0 ,getSize().width, getSize().height);
				/* Ripristina il colore precedente */
				offScreenGraphics.setColor(g.getColor());
				/* Disegna sul offScreenGraphics invece che sulla finestra */
				paint(offScreenGraphics); 
				/* Disegna sulla finestra */
				g.drawImage(offScreenImage, 0, 0, this);
			} 
		else {
				offScreenImage = createImage(getSize().width,getSize().height);
				paint(g);
			}
	}
	
	/**
	 * Disegna sull'applet
	 */
	
	public void paint(Graphics g) {
		tela.paint(g);
	}

	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	/**
	 * Gestisci gli eventi relativi al cambiamento dei due campi TextField
	 */
	
	public void actionPerformed(ActionEvent arg0) {
		errore.setText("");
		if(arg0.getSource().equals(nMolle)) tela.add(Integer.parseInt(nMolle.getText()));
		else if(arg0.getSource().equals(molla)) {
			try {
			Pallina p = tela.getPallina(Integer.parseInt(molla.getText())-1);
			coloreB.setValue(p.getRgbColor());
			massa.setValue((int)p.getMassa());
			dPalline.setValue(p.getDiametroPalla());
			attrito.setValue((int)p.getAttrito());
			
			Punti punto = tela.getPunto(Integer.parseInt(molla.getText())-1);
			coloreP.setValue(punto.getRgbColor());
			dBasi.setValue(punto.getDiametroPunto());
							Forza f = tela.getForza(Integer.parseInt(molla.getText())-1);
			kElastica.setValue((int)f.getKElastica());
			errore.setText("Modifica la molla n. "+(Integer.parseInt(molla.getText())));
			}
			catch(ArrayIndexOutOfBoundsException e) { errore.setText("Modifica tutte le molle"); System.out.println(e.getLocalizedMessage());}
		}
	}

}//Elastico
